package com.luoqiz.caffeine.config;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.github.benmanes.caffeine.cache.Caffeine;

@Configuration
@EnableCaching // 开启缓存
public class CaffeineConfig {
	public static final int DEFAULT_MAXSIZE = 10000;
	public static final int DEFAULT_TTL = 600;
	public static final int DEFAULT_CAPACITY = 30;

	/**
	 * 定义cache名称、超时时长（秒）、最大容量 每个cache缺省：10秒超时、最多缓存50000条数据，需要修改可以在构造方法的参数中指定。
	 */
	public enum CachesByExpiry {
		listMember(7200, 1000), // 有效期2个小时 , 最大容量1000
		;
		CachesByExpiry() {
		}

		CachesByExpiry(int ttl) {
			this.ttl = ttl;
		}

		CachesByExpiry(int ttl, int maxSize) {
			this.ttl = ttl;
			this.maxSize = maxSize;
		}

		private int maxSize = DEFAULT_MAXSIZE; // 最大數量
		private int ttl = DEFAULT_TTL; // 过期时间（秒）

		public int getMaxSize() {
			return maxSize;
		}

		public int getTtl() {
			return ttl;
		}
	}


	public enum CachesBySize {
		dictCatalogItem(2, 4), // 初始容量为2，最大容量为4，当超过4个的时候会启动淘汰策略
		;
		CachesBySize() {
		}

		CachesBySize(int initialCapacity) {
			this.initialCapacity = initialCapacity;
		}

		CachesBySize(int initialCapacity, int maxSize) {
			this.initialCapacity = initialCapacity;
			this.maxSize = maxSize;
		}

		private int maxSize = DEFAULT_MAXSIZE; // 最大數量
		private int initialCapacity = DEFAULT_CAPACITY; // 初始容量

		public int getMaxSize() {
			return maxSize;
		}

		public int getInitialCapacity() {
			return initialCapacity;
		}

	}

	/**
	 * 创建基于Caffeine的Cache Manager
	 * 详情参考：https://blog.csdn.net/qq_35981283/article/details/82386047
	 * 
	 * @return
	 */
	@Bean
	@Primary
	public CacheManager caffeineCacheManager() {
		SimpleCacheManager cacheManager = new SimpleCacheManager();
		ArrayList<CaffeineCache> caches = new ArrayList<CaffeineCache>();
		for (CachesByExpiry c : CachesByExpiry.values()) {
			caches.add(new CaffeineCache(c.name(), Caffeine.newBuilder().recordStats()
					.expireAfterWrite(c.getTtl(), TimeUnit.SECONDS).maximumSize(c.getMaxSize()).build()));
		}
		for (CachesBySize c : CachesBySize.values()) {
			caches.add(new CaffeineCache(c.name(), Caffeine.newBuilder().recordStats()
					.initialCapacity(c.getInitialCapacity()).maximumSize(c.getMaxSize()).build()));
		}
		cacheManager.setCaches(caches);
		return cacheManager;
	}
}
